#ifndef _PCF50606_H
#define _PCF50606_H

/* Philips PCF50606 Power Managemnt Unit (PMU) driver
 * (C) 2006-2007 by OpenMoko, Inc.
 * Author: Harald Welte <laforge@openmoko.org>
 *
 */

enum pfc50606_regs {
	PCF50606_REG_ID		= 0x00,
	PCF50606_REG_OOCS	= 0x01,
	PCF50606_REG_INT1	= 0x02,	/* Interrupt Status */
	PCF50606_REG_INT2	= 0x03,	/* Interrupt Status */
	PCF50606_REG_INT3	= 0x04,	/* Interrupt Status */
	PCF50606_REG_INT1M	= 0x05,	/* Interrupt Mask */
	PCF50606_REG_INT2M	= 0x06,	/* Interrupt Mask */
	PCF50606_REG_INT3M	= 0x07,	/* Interrupt Mask */
	PCF50606_REG_OOCC1	= 0x08,
	PCF50606_REG_OOCC2	= 0x09,
	PCF50606_REG_RTCSC	= 0x0a,	/* Second */
	PCF50606_REG_RTCMN	= 0x0b,	/* Minute */
	PCF50606_REG_RTCHR	= 0x0c,	/* Hour */
	PCF50606_REG_RTCWD	= 0x0d,	/* Weekday */
	PCF50606_REG_RTCDT	= 0x0e,	/* Day */
	PCF50606_REG_RTCMT	= 0x0f,	/* Month */
	PCF50606_REG_RTCYR	= 0x10,	/* Year */
	PCF50606_REG_RTCSCA	= 0x11, /* Alarm Second */
	PCF50606_REG_RTCMNA	= 0x12, /* Alarm Minute */
	PCF50606_REG_RTCHRA	= 0x13, /* Alarm Hour */
	PCF50606_REG_RTCWDA	= 0x14, /* Alarm Weekday */
	PCF50606_REG_RTCDTA	= 0x15, /* Alarm Day */
	PCF50606_REG_RTCMTA	= 0x16, /* Alarm Month */
	PCF50606_REG_RTCYRA	= 0x17, /* Alarm Year */
	PCF50606_REG_PSSC	= 0x18,	/* Power sequencing */
	PCF50606_REG_PWROKM	= 0x19,	/* PWROK mask */
	PCF50606_REG_PWROKS	= 0x1a,	/* PWROK status */
	PCF50606_REG_DCDC1	= 0x1b,
	PCF50606_REG_DCDC2	= 0x1c,
	PCF50606_REG_DCDC3	= 0x1d,
	PCF50606_REG_DCDC4	= 0x1e,
	PCF50606_REG_DCDEC1	= 0x1f,
	PCF50606_REG_DCDEC2	= 0x20,
	PCF50606_REG_DCUDC1	= 0x21,
	PCF50606_REG_DCUDC2	= 0x22,
	PCF50606_REG_IOREGC	= 0x23,
	PCF50606_REG_D1REGC1	= 0x24,
	PCF50606_REG_D2REGC1	= 0x25,
	PCF50606_REG_D3REGC1	= 0x26,
	PCF50606_REG_LPREGC1	= 0x27,
	PCF50606_REG_LPREGC2	= 0x28,
	PCF50606_REG_MBCC1	= 0x29,
	PCF50606_REG_MBCC2	= 0x2a,
	PCF50606_REG_MBCC3	= 0x2b,
	PCF50606_REG_MBCS1	= 0x2c,
	PCF50606_REG_BBCC	= 0x2d,
	PCF50606_REG_ADCC1	= 0x2e,
	PCF50606_REG_ADCC2	= 0x2f,
	PCF50606_REG_ADCS1	= 0x30,
	PCF50606_REG_ADCS2	= 0x31,
	PCF50606_REG_ADCS3	= 0x32,
	PCF50606_REG_ACDC1	= 0x33,
	PCF50606_REG_BVMC	= 0x34,
	PCF50606_REG_PWMC1	= 0x35,
	PCF50606_REG_LEDC1	= 0x36,
	PCF50606_REG_LEDC2	= 0x37,
	PCF50606_REG_GPOC1	= 0x38,
	PCF50606_REG_GPOC2	= 0x39,
	PCF50606_REG_GPOC3	= 0x3a,
	PCF50606_REG_GPOC4	= 0x3b,
	PCF50606_REG_GPOC5	= 0x3c,
	__NUM_PCF50606_REGS
};

enum pcf50606_reg_oocs {
	PFC50606_OOCS_ONKEY	= 0x01,
	PCF50606_OOCS_EXTON	= 0x02,
	PCF50606_OOCS_PWROKRST	= 0x04,
	PCF50606_OOCS_BATOK	= 0x08,
	PCF50606_OOCS_BACKOK	= 0x10,
	PCF50606_OOCS_CHGOK	= 0x20,
	PCF50606_OOCS_TEMPOK	= 0x40,
	PCF50606_OOCS_WDTEXP	= 0x80,
};

enum pcf50606_reg_oocc1 {
	PCF50606_OOCC1_GOSTDBY	= 0x01,
	PCF50606_OOCC1_TOTRST	= 0x02,
	PCF50606_OOCC1_CLK32ON	= 0x04,
	PCF50606_OOCC1_WDTRST	= 0x08,
	PCF50606_OOCC1_RTCWAK	= 0x10,
	PCF50606_OOCC1_CHGWAK	= 0x20,
	PCF50606_OOCC1_EXTONWAK_HIGH	= 0x40,
	PCF50606_OOCC1_EXTONWAK_LOW	= 0x80,
	PCF50606_OOCC1_EXTONWAK_NO_WAKEUP = 0x3f,
};

enum pcf50606_reg_oocc2 {
	PCF50606_OOCC2_ONKEYDB_NONE	= 0x00,
	PCF50606_OOCC2_ONKEYDB_14ms	= 0x01,
	PCF50606_OOCC2_ONKEYDB_62ms	= 0x02,
	PCF50606_OOCC2_ONKEYDB_500ms	= 0x03,
	PCF50606_OOCC2_EXTONDB_NONE	= 0x00,
	PCF50606_OOCC2_EXTONDB_14ms	= 0x04,
	PCF50606_OOCC2_EXTONDB_62ms	= 0x08,
	PCF50606_OOCC2_EXTONDB_500ms	= 0x0c,
};

enum pcf50606_reg_int1 {
	PCF50606_INT1_ONKEYR	= 0x01,	/* ONKEY rising edge */
	PCF50606_INT1_ONKEYF	= 0x02,	/* ONKEY falling edge */
	PCF50606_INT1_ONKEY1S	= 0x04,	/* OMKEY at least 1sec low */
	PCF50606_INT1_EXTONR	= 0x08,	/* EXTON rising edge */
	PCF50606_INT1_EXTONF	= 0x10,	/* EXTON falling edge */
	PCF50606_INT1_SECOND	= 0x40,	/* RTC periodic second interrupt */
	PCF50606_INT1_ALARM	= 0x80, /* RTC alarm time is reached */
};

enum pcf50606_reg_int2 {
	PCF50606_INT2_CHGINS	= 0x01, /* Charger inserted */
	PCF50606_INT2_CHGRM	= 0x02, /* Charger removed */
	PCF50606_INT2_CHGFOK	= 0x04,	/* Fast charging OK */
	PCF50606_INT2_CHGERR	= 0x08,	/* Error in charging mode */
	PCF50606_INT2_CHGFRDY	= 0x10,	/* Fast charge completed */
	PCF50606_INT2_CHGPROT	= 0x20,	/* Charging protection interrupt */
	PCF50606_INT2_CHGWD10S	= 0x40,	/* Charger watchdig expires in 10s */
	PCF50606_INT2_CHGWDEXP	= 0x80,	/* Charger watchdog expires */
};

enum pcf50606_reg_int3 {
	PCF50606_INT3_ADCRDY	= 0x01,	/* ADC conversion finished */
	PCF50606_INT3_ACDINS	= 0x02,	/* Accessory inserted */
	PCF50606_INT3_ACDREM	= 0x04, /* Accessory removed */
	PCF50606_INT3_TSCPRES	= 0x08,	/* Touch screen pressed */
	PCF50606_INT3_LOWBAT	= 0x40,	/* Low battery voltage */
	PCF50606_INT3_HIGHTMP	= 0x80, /* High temperature */
};

/* used by PSSC, PWROKM, PWROKS, */
enum pcf50606_regu {
	PCF50606_REGU_DCD	= 0x01,	/* DCD in phase 2 */
	PCF50606_REGU_DCDE	= 0x02,	/* DCDE in phase 2 */
	PCF50606_REGU_DCUD	= 0x04,	/* DCDU in phase 2 */
	PCF50606_REGU_IO	= 0x08,	/* IO in phase 2 */
	PCF50606_REGU_D1	= 0x10, /* D1 in phase 2 */
	PCF50606_REGU_D2	= 0x20,	/* D2 in phase 2 */
	PCF50606_REGU_D3	= 0x40,	/* D3 in phase 2 */
	PCF50606_REGU_LP	= 0x80,	/* LP in phase 2 */
};

enum pcf50606_reg_dcdc4 {
	PCF50606_DCDC4_MODE_AUTO	= 0x00,
	PCF50606_DCDC4_MODE_PWM		= 0x01,
	PCF50606_DCDC4_MODE_PCF		= 0x02,
	PCF50606_DCDC4_OFF_FLOAT	= 0x00,
	PCF50606_DCDC4_OFF_BYPASS	= 0x04,
	PCF50606_DCDC4_OFF_PULLDOWN	= 0x08,
	PCF50606_DCDC4_CURLIM_500mA	= 0x00,
	PCF50606_DCDC4_CURLIM_750mA	= 0x10,
	PCF50606_DCDC4_CURLIM_1000mA	= 0x20,
	PCF50606_DCDC4_CURLIM_1250mA	= 0x30,
	PCF50606_DCDC4_TOGGLE		= 0x40,
	PCF50606_DCDC4_REGSEL_DCDC2	= 0x80,
};

enum pcf50606_reg_dcdec2 {
	PCF50606_DCDEC2_MODE_AUTO	= 0x00,
	PCF50606_DCDEC2_MODE_PWM	= 0x01,
	PCF50606_DCDEC2_MODE_PCF	= 0x02,
	PCF50606_DCDEC2_OFF_FLOAT	= 0x00,
	PCF50606_DCDEC2_OFF_BYPASS	= 0x04,
};

enum pcf50606_reg_dcudc2 {
	PCF50606_DCUDC2_MODE_AUTO	= 0x00,
	PCF50606_DCUDC2_MODE_PWM	= 0x01,
	PCF50606_DCUDC2_MODE_PCF	= 0x02,
	PCF50606_DCUDC2_OFF_FLOAT	= 0x00,
	PCF50606_DCUDC2_OFF_BYPASS	= 0x04,
};

enum pcf50606_reg_adcc1 {
	PCF50606_ADCC1_TSCMODACT	= 0x01,
	PCF50606_ADCC1_TSCMODSTB	= 0x02,
	PCF50606_ADCC1_TRATSET		= 0x04,
	PCF50606_ADCC1_NTCSWAPE		= 0x08,
	PCF50606_ADCC1_NTCSWAOFF	= 0x10,
	PCF50606_ADCC1_EXTSYNCBREAK	= 0x20,
	/* reserved */
	PCF50606_ADCC1_TSCINT		= 0x80,
};

enum pcf50606_reg_adcc2 {
	PCF50606_ADCC2_ADCSTART		= 0x01,
	/* see enum pcf50606_adcc2_adcmux */
	PCF50606_ADCC2_SYNC_NONE	= 0x00,
	PCF50606_ADCC2_SYNC_TXON	= 0x20,
	PCF50606_ADCC2_SYNC_PWREN1	= 0x40,
	PCF50606_ADCC2_SYNC_PWREN2	= 0x60,
	PCF50606_ADCC2_RES_10BIT	= 0x00,
	PCF50606_ADCC2_RES_8BIT		= 0x80,
};

#define PCF50606_ADCC2_ADCMUX_MASK	(0xf << 1)

#define ADCMUX_SHIFT	1
enum pcf50606_adcc2_adcmux {
	PCF50606_ADCMUX_BATVOLT_RES	= 0x0 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_BATVOLT_SUBTR	= 0x1 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_ADCIN1_RES	= 0x2 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_ADCIN1_SUBTR	= 0x3 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_BATTEMP		= 0x4 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_ADCIN2		= 0x5 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_ADCIN3		= 0x6 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_ADCIN3_RATIO	= 0x7 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_XPOS		= 0x8 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_YPOS		= 0x9 << ADCMUX_SHIFT,
	PCF50606_ADCMUX_P1		= 0xa << ADCMUX_SHIFT,
	PCF50606_ADCMUX_P2		= 0xb << ADCMUX_SHIFT,
	PCF50606_ADCMUX_BATVOLT_ADCIN1	= 0xc << ADCMUX_SHIFT,
	PCF50606_ADCMUX_XY_SEQUENCE	= 0xe << ADCMUX_SHIFT,
	PCF50606_P1_P2_RESISTANCE	= 0xf << ADCMUX_SHIFT,
};

enum pcf50606_adcs2 {
	PCF50606_ADCS2_ADCRDY		= 0x80,
};

enum pcf50606_reg_mbcc1 {
	PCF50606_MBCC1_CHGAPE		= 0x01,
	PCF50606_MBCC1_AUTOFST		= 0x02,
#define	PCF50606_MBCC1_CHGMOD_MASK	  0x1c
#define	PCF50606_MBCC1_CHGMOD_SHIFT	  2
	PCF50606_MBCC1_CHGMOD_QUAL	= 0x00,
	PCF50606_MBCC1_CHGMOD_PRE	= 0x04,
	PCF50606_MBCC1_CHGMOD_TRICKLE	= 0x08,
	PCF50606_MBCC1_CHGMOD_FAST_CCCV	= 0x0c,
	PCF50606_MBCC1_CHGMOD_FAST_NOCC	= 0x10,
	PCF50606_MBCC1_CHGMOD_FAST_NOCV	= 0x14,
	PCF50606_MBCC1_CHGMOD_FAST_SW	= 0x18,
	PCF50606_MBCC1_CHGMOD_IDLE	= 0x1c,
	PCF50606_MBCC1_DETMOD_LOWCHG	= 0x20,
	PCF50606_MBCC1_DETMOD_WDRST	= 0x40,
};

enum pcf50606_reg_bvmc {
	PCF50606_BVMC_LOWBAT		= 0x01,
	PCF50606_BVMC_THRSHLD_NULL	= 0x00,
	PCF50606_BVMC_THRSHLD_2V8	= 0x02,
	PCF50606_BVMC_THRSHLD_2V9	= 0x04,
	PCF50606_BVMC_THRSHLD_3V	= 0x08,
	PCF50606_BVMC_THRSHLD_3V1	= 0x08,
	PCF50606_BVMC_THRSHLD_3V2	= 0x0a,
	PCF50606_BVMC_THRSHLD_3V3	= 0x0c,
	PCF50606_BVMC_THRSHLD_3V4	= 0x0e,
	PCF50606_BVMC_DISDB		= 0x10,
};

/* this is to be provided by the board implementation */
extern const u_int8_t pcf50606_initial_regs[__NUM_PCF50606_REGS];

void pcf50606_reg_write(u_int8_t reg, u_int8_t val);

u_int8_t pcf50606_reg_read(u_int8_t reg);

void pcf50606_reg_set_bit_mask(u_int8_t reg, u_int8_t mask, u_int8_t val);
void pcf50606_reg_clear_bits(u_int8_t reg, u_int8_t bits);

void pcf50606_init(void);
void pcf50606_charge_autofast(int on);

#endif /* _PCF50606_H */

